#include "utils.h"
#include <QDebug>


QString Utils::m_portName="";
Utils::Utils(QObject *parent)
    : QObject(parent)
{
    m_Flag_Sub33=true;
}

Utils* Utils::instance()
{
    static Utils s_instance;
    return &s_instance;
}


QByteArray Utils::calculateChecksum(QByteArray arr)
{
    QByteArray ret=arr;
    if((arr.size()<(LEN+1)) || (arr.size()<(LEN+arr[LEN]+1)))
    {
        return ret;
    }
    quint8 checksum = 0;
    quint8 len=arr.at(LEN);
    for(int i=0;i<(LEN+arr[LEN]+1);i++)
    {
       checksum+=arr.at(i);
    }
    ret.append(checksum);
    ret.append(0x16);
    return ret;
}

//QByteArray Utils::add33(QByteArray arr)
//{
//    if(arr.size()<DI0 || arr.at(LEN)==0 )
//    {
//        return QByteArray();
//    }
//    QByteArray ret=arr;
//    int len=arr[LEN];
//    if(len>arr.size())
//    {
//        return QByteArray();
//    }
//    for(int i=LEN+1;i<len;i++)
//    {
//        ret[i]=arr.at(i)+0x33;
//    }
//    return ret;
//}

//QByteArray Utils::sub33(QByteArray arr)
//{
//    if (arr.size() < DI0 || arr.at(LEN) == 0 )
//    {
//        return QByteArray();
//    }

//    QByteArray ret = arr;
//    int len = arr[LEN];

//    if (len > arr.size())
//    {
//        return QByteArray();
//    }

//    for (int i = LEN + 1; i < len; i++)
//    {
//        ret[i] = arr.at(i) - 0x33;
//    }

//    return ret;
//}

void Utils::Frameadd33(QByteArray &arr)
{
    if (arr.size() < DI0 || arr.at(LEN) == 0 )
    {
        qDebug()<<"return";
        return;
    }

    int len = static_cast<unsigned char>(arr[LEN]);

    for (int i = LEN + 1; i < (LEN+len+1); ++i)
    {
        arr[i] = arr.at(i) + 0x33;
    }
}

void Utils::Framesub33(QByteArray &arr)
{
    if (arr.size() < 4+DI0 || arr.at(4+LEN) == 0 )
    {
        return;
    }

    int len = static_cast<unsigned char>(arr[4+LEN]);

    if (len > arr.size())
    {
        return;
    }

    for (int i = 4+LEN + 1; i < len; ++i)
    {
        arr[i] = arr.at(i) - 0x33;
    }
}

QByteArray Utils::add33(const QByteArray &input)
{
    QByteArray result = input;
    for (int i = 0; i < result.size(); ++i) {
        result[i] = result[i] + 0x33;
    }
    return result;
}

QByteArray Utils::sub33(const QByteArray &input)
{
    QByteArray result = input;
    for (int i = 0; i < result.size(); ++i) {
        result[i] = result[i] - 0x33;
    }
    return result;
}

//添加空格
QString Utils::StringAddSpace(QString str)
{
    QString output;
    for (int i = 0; i < str.length(); i += 2)
    {
        output.append(str.mid(i, 2));  // 每次获取两个字符
        if (i + 2 < str.length())
        {
            output.append(" ");  // 在每两个字符后面添加空格
        }
    }
    return output;
}

QByteArray Utils::hexStringToByteArray(const QString &hexString)
{
    QByteArray byteArray;
    QString cleanHex = hexString.trimmed().remove(' ');

    // 如果字符串长度是奇数，补个0在前面
    if (cleanHex.length() % 2 != 0) {
        cleanHex = "0" + cleanHex;
    }

    for (int i = 0; i < cleanHex.length(); i += 2) {
        QString byteString = cleanHex.mid(i, 2);  // 每次取2个字符
        bool ok;
        char byte = static_cast<char>(byteString.toUInt(&ok, 16));
        if (ok) {
            byteArray.append(byte);
        } else {
            // 如果出现非法字符，可以根据需求处理，比如直接return空，或者继续
            byteArray.clear();
            break;
        }
    }
    return byteArray;
}

QByteArray Utils::reverseByteArray(const QByteArray &input)
{
    QByteArray output = input;

    int i = 0;
    int j = output.size() - 1;

    while (i < j) {
        char temp = output[i];
        output[i] = output[j];
        output[j] = temp;
        ++i;
        --j;
    }

    return output;
}

/*组建命令帧
QByteArray cmd,     命令
 QByteArray id,     数据标识
int dataLen,        数据长度（除了数据标识之外的数据长度）
QByteArray data     其他数据
*/
QByteArray Utils::createCommandFrame(unsigned char cmd, QByteArray id, unsigned char dataLen, QByteArray data)
{
    QByteArray frame;
    frame.append((char)(0x68));
    frame.append(instance()->getAddress());
    frame.append((char)(0x68));
    frame.append(cmd);
    if(dataLen==0)
    {
        frame.append((char)(0x04));
        frame.append(id);
    }
    else
    {
        unsigned char len=4+dataLen;
        frame.append(len);
        frame.append(id);
        frame.append(data);
    }
    instance()->Frameadd33(frame);
    QByteArray ret=instance()->calculateChecksum(frame);
    return ret;
}

QByteArray Utils::createCommandFrameNoDI(unsigned char cmd, unsigned char dataLen, QByteArray data)
{
    QByteArray frame;
    frame.append((char)(0x68));
    frame.append(instance()->getAddress());
    frame.append((char)(0x68));
    frame.append(cmd);
    unsigned char len=dataLen;
    frame.append(len);
    frame.append(data);

    instance()->Frameadd33(frame);
    QByteArray ret=instance()->calculateChecksum(frame);
    return ret;
}

QByteArray Utils::doubleToBCDArray3Dot3(double value)
{
    QByteArray result;

      // 将 double 转换为 NNN.NNN 的字符串（带 3 位整数 + 3 位小数）
      QString str = QString("%1").arg(value, 7, 'f', 3);  // 例如 "123.456"
      str.remove('.');  // 移除小数点，得到 "123456"

      // 确保字符串长度为6，不足则补0
      while (str.length() < 6)
          str.prepend("0");

      // 每两个数字组成一个 BCD 字节
      for (int i = 0; i < 6; i += 2) {
          QString twoDigits = str.mid(i, 2);
          bool ok;
          quint8 bcd = twoDigits.toUInt(&ok, 10);
          if (ok) {
              result.append(static_cast<char>(bcd));
          } else {
              result.append('\0');  // 错误时补0
          }
      }

      return result;
}

//每两个字符作为一个字节BCD编码
QByteArray Utils::decimalStringToBcd(const QString &decimalStr)
{
    QByteArray bcd;

       if (decimalStr.length() % 2 != 0) {
           // 若长度为奇数，前补0
           QString paddedStr = "0" + decimalStr;
           return decimalStringToBcd(paddedStr);
       }

       for (int i = 0; i < decimalStr.length(); i += 2) {
           QChar highChar = decimalStr[i];
           QChar lowChar = decimalStr[i + 1];

           if (!highChar.isDigit() || !lowChar.isDigit())
               return {};  // 非数字字符，返回空 QByteArray 表示失败

           int high = highChar.digitValue();
           int low = lowChar.digitValue();

           char bcdByte = (high << 4) | low;
           bcd.append(bcdByte);
       }

       return bcd;
}

double Utils::bcdArrayToDouble3Dot3(const QByteArray &bcd)
{
    if (bcd.size() != 3) {
          qWarning() << "BCD长度应为3字节";
          return 0.0;
      }

      QString digits;

      for (char byte : bcd) {
          unsigned char ubyte = static_cast<unsigned char>(byte);
          int high = (ubyte >> 4) & 0x0F;
          int low = ubyte & 0x0F;

          if (high > 9 || low > 9) {
              qWarning() << "无效的BCD码: " << QString("0x%1").arg(ubyte, 2, 16, QLatin1Char('0'));
              return 0.0;
          }

          digits.append(QString::number(high));
          digits.append(QString::number(low));
      }

      // 插入小数点，得到 NNN.NNN
      digits.insert(3, '.');  // 在第3位后插入'.'

      return digits.toDouble();
}

int Utils::bcdToInt(const QByteArray &bcd)
{
    QString digits;

    for (char byte : bcd) {
        quint8 ubyte = static_cast<quint8>(byte);
        int high = (ubyte >> 4) & 0x0F;
        int low = ubyte & 0x0F;

        if (high > 9 || low > 9) {
            qWarning() << "非法 BCD 字节:" << QString("0x%1").arg(ubyte, 2, 16, QLatin1Char('0'));
            return 0;
        }

        digits.append(QString::number(high));
        digits.append(QString::number(low));
    }

    return digits.toInt();
}

QByteArray Utils::intToBcd(int number, int minBytes)
{
    QByteArray result;

    if (number < 0) {
        qWarning() << "不支持负数 BCD 编码";
        return result;
    }

    QString numStr = QString::number(number);

    // 补0：确保偶数位
    if (numStr.length() % 2 != 0) {
        numStr.prepend('0');
    }

    // 补字节数（每字节2位）
    while (numStr.length() < minBytes * 2) {
        numStr.prepend("00");
    }

    // 生成 BCD：每2位十进制变成1字节（高4位+低4位）
    for (int i = 0; i < numStr.length(); i += 2) {
        int high = numStr[i].digitValue();
        int low = numStr[i + 1].digitValue();

        if (high < 0 || high > 9 || low < 0 || low > 9) {
            qWarning() << "非法数字部分：" << numStr.mid(i, 2);
            result.append('\0');
        } else {
            result.append(static_cast<char>((high << 4) | low));
        }
    }

    return result;
}

QByteArray Utils::stringToBCD(const QString &decimalString)
{
    QByteArray bcd;
    QString str = decimalString;

    // 若字符串长度为奇数，前面补0
    if (str.length() % 2 != 0)
        str.prepend('0');

    for (int i = 0; i < str.length(); i += 2) {
        char highNibble = str.at(i).toLatin1() - '0';
        char lowNibble = str.at(i + 1).toLatin1() - '0';
        char byte = (highNibble << 4) | lowNibble;
        bcd.append(byte);
    }

    return bcd;
}

QString Utils::bcdToDecimalString(const QByteArray &bcd, int decimalDigits)
{
    if (bcd.isEmpty() || decimalDigits < 0)
        return "Invalid Input";

    QString digits;
    for (char byte : bcd) {
        int high = (byte & 0xF0) >> 4;
        int low = byte & 0x0F;

        // 严格验证是BCD
        if (high > 9 || low > 9)
            return "Invalid BCD";

        digits += QString::number(high);
        digits += QString::number(low);
    }

    // 保证整数部分至少有一位，前补零
    if (digits.length() <= decimalDigits) {
        digits = QString("0").repeated(decimalDigits - digits.length() + 1) + digits;
    }

    digits.insert(digits.length() - decimalDigits, '.');
    return digits;
}

//QString Utils::getSerialPortName()
//{
//    return m_portName;
//}

//void Utils::setSerialPortName(QString name)
//{
//    m_portName=name;
//}

QSerialPort::DataBits Utils::getSerialPortDataBits()
{
    return m_dataBits;
}

void Utils::setSerialPortDataBit(QSerialPort::DataBits b)
{
    m_dataBits=b;
}

QSerialPort::Parity Utils::getSerialPortParity()
{
    return m_parity;
}

void Utils::setSerialPortParity(QSerialPort::Parity p)
{
    m_parity=p;
}

QSerialPort::StopBits Utils::getSerialPortStopBits()
{
    return m_stopBits;
}

void Utils::setSerialPortStopBits(QSerialPort::StopBits s)
{
    m_stopBits=s;
}

QSerialPort::BaudRate Utils::getSerialBaudRate()
{
    return m_baudRate;
}

void Utils::setSerialBaudRate(QSerialPort::BaudRate b)
{
    m_baudRate=b;
}

int Utils::getTimeOutMs()
{
    return m_readTimeoutMs;
}

void Utils::setTimeOutMs(int timeout)
{
    m_readTimeoutMs=timeout;
}

QByteArray Utils::getPwdLevel()
{
    return m_pwdLevel;
}

void Utils::setPwdLevel(QByteArray l)
{
    m_pwdLevel=l;
}

QByteArray Utils::getPwd()
{
    return m_pwd;
}

void Utils::setPwd(QByteArray pwd)
{
    m_pwd=pwd;
}

QByteArray Utils::getAddress()
{
    return m_addres;
}

void Utils::setAddress(QByteArray a)
{
    m_addres=a;
}


bool Utils::isSub33()
{
    return m_Flag_Sub33;
}

void Utils::setSub33(bool b)
{
    m_Flag_Sub33=b;
}
